package com.wehealth.three.lib_connect.device.bluetoothdevice;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.RequiresApi;


import com.wehealth.three.lib_connect.R;
import com.wehealth.three.lib_connect.device.usbdevice.data.ParseOriginEcgData;
import com.wehealth.three.lib_connect.utils.AppGlobals;
import com.wehealth.three.lib_connect.utils.ByteDataUtil;
import com.wehealth.three.lib_connect.utils.DateUtil;
import com.wehealth.three.lib_connect.utils.PreferenceUtils;


import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.UUID;

/****
 * ble蓝牙发送指令获取设备信息绑定设备
 */

public class BleBindThread extends Thread {
    //该变量记录蓝牙原始数据是否收集完成
    private boolean isFinish = false;
    //存储收集到的全部的蓝牙数据
    private ArrayList<Byte> rowData = new ArrayList<Byte>();
    protected final int BT_CONNECT_DEVICE_ERROR = 899;
    protected final int DISMISS_PROGRESS_DIALOG = 801;
    protected final int SHOW_PROGRESS_DIALOG = 800;
    protected final int BT_CONNECT_FAILED = 997;
    private final int OBTAIN_SERIAL = 980;
    private BluetoothLeScanner bleScanner;
    private BluetoothGatt mBleGatt;
    private BluetoothGattCharacteristic bleWriteCharacteristic;
    private StringBuilder stringBuilder = new StringBuilder();
    private BluetoothDevice bluetoothDevice;
    private String bleMacAddress;
    private Handler handler;
    private Context context;
    private boolean scanSwitch;

    public BleBindThread(Context ctx, Handler h) {
        handler = h;
        context = ctx;
        BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();
        bleScanner = mBtAdapter.getBluetoothLeScanner();
    }

    @SuppressLint("MissingPermission")
    private void connectBleDevice() {
        bleScanner.stopScan(scanCallback);
        Message msg = handler.obtainMessage(SHOW_PROGRESS_DIALOG);
        msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_connecting);
        handler.sendMessage(msg);
        mBleGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback);
    }


    BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
        @SuppressLint("MissingPermission")
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            switch (newState) {
                case BluetoothProfile.STATE_CONNECTING:
                    Message msg = handler.obtainMessage(SHOW_PROGRESS_DIALOG);
                    msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_connecting);
                    handler.sendMessage(msg);
                    break;
                case BluetoothProfile.STATE_CONNECTED:
                    gatt.discoverServices();
                    if (bluetoothDevice != null) {
                        bleMacAddress = bluetoothDevice.getAddress();
                    }
                    PreferenceUtils.getInstance().setDeviceBluetoothType(false);
                    handler.sendEmptyMessage(DISMISS_PROGRESS_DIALOG);
                    break;
                case BluetoothProfile.STATE_DISCONNECTED:
                    Log.e("TAG", "蓝牙断开");
                    msg = handler.obtainMessage(BT_CONNECT_DEVICE_ERROR);
                    msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_bt_broken);
                    handler.sendMessage(msg);
                    break;
                case BluetoothProfile.STATE_DISCONNECTING:
                    Log.e("TAG", "蓝牙正在断开...");
                    handler.sendEmptyMessage(SHOW_PROGRESS_DIALOG);
                    break;
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            BluetoothGattService gattService = gatt.getService(UUID.fromString("974CBE30-3E83-465E-ACDE-6F92FE712134"));// 获取到服务的通道
            //获取到Notify的Characteristic通道 这个根据协议来定  如果设备厂家给的协议不是Notify的话  就不用做以下操作了
            BluetoothGattCharacteristic notifyCharacteristic = gattService.getCharacteristic(UUID.fromString("974CBE31-3E83-465E-ACDE-6F92FE712134"));
            @SuppressLint("MissingPermission")
            boolean ding = gatt.setCharacteristicNotification(notifyCharacteristic, true);
            enableNotification(gatt, ding, notifyCharacteristic);
            bleWriteCharacteristic = gattService.getCharacteristic(UUID.fromString("974CBE32-3E83-465E-ACDE-6F92FE712134"));
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
        }


        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            stringBuilder.delete(0, stringBuilder.length());
            //获取蓝牙发送的原始数据  是一个字节数组 内部的字节值是一个16进制数
            byte[] bleData = characteristic.getValue();
            //将原始数据转化为字符串
            String rowHexString = ByteDataUtil.toHex(bleData, " ");
            Log.e("TAG", "rowHexString:" + rowHexString);
            //收集全部的有效数据
            for (byte data : bleData) {
                //对接收到的数据进行判断 数据不是0x00就是有效数据保存到数据集合中
                if (data != 0x00) {
                    rowData.add(data);
                } else {
                    isFinish = true;
                    break;
                }
            }
            //处理解析蓝牙数据
            if (isFinish) {
                //存储去除枕头和枕尾的有效数据
                byte[] byteSerial = new byte[rowData.size() - 9];
                byte[] byteCodeSerial = new byte[rowData.size() - 5];
                //对枕头和枕尾进行判断是否符合条件
                if (rowData.get(2) == (byte) 0x15 && rowData.get(rowData.size() - 1) == (byte) 0x5A) {
                    //单独处理序列号
                    for (int i = 7; i < rowData.size() - 2; i++) {
                        //出列序列号的数据的时候需要取补码
                        byteSerial[i - 7] = (byte) (rowData.get(i) ^ 0x11);
                    }
                    // 加上CXX的序列号
                    for (int i = 3; i < rowData.size() - 2; i++) {
                        if (i < 7) {
                            //CXX的数据直接取
                            byteCodeSerial[i - 3] = (byte) rowData.get(i);
                        } else {
                            byteCodeSerial[i - 3] = (byte) (rowData.get(i) ^ 0x11);
                        }
                    }
                }
                String serialHexString = ByteDataUtil.toHex(byteSerial, " ");
                Log.e("TAG", "serialHexString： " + serialHexString);
                String serialNumber = new String(byteSerial);
                String serialCodeNumber = new String(byteCodeSerial);
                Log.e("TAG", "serialNumber：" + serialNumber);
                Log.e("TAG", "serialCodeNumber： " + serialCodeNumber);
                stringBuilder.append("serialHexString:").append(serialHexString).append("\n")
                        .append("serialNumber:").append(serialNumber).append("\n")
                        .append("serialCodeNumber:").append(serialCodeNumber).append("\n");

                try {
                    String name = DateUtil.sdf_yyyyMMddHHmmss.format(new Date());
                    FileOutputStream fos = new FileOutputStream(context.getExternalCacheDir() + File.separator + "serial_" + name + ".txt");//CommUtils.crash_log
                    fos.write(stringBuilder.toString().getBytes());
                    fos.close();
                } catch (Exception e) {
                    Log.e("TAG", "an error occurred while writing file...", e);
                }
                if (serialCodeNumber.contains(" ")) {
                    String[] serialNo = serialCodeNumber.split(" ");
                    Message msg = handler.obtainMessage(OBTAIN_SERIAL);
                    msg.obj = serialNo[1] + " " + bleMacAddress;
                    handler.sendMessage(msg);
                    isFinish = false;
                } else {
                    Message msg = handler.obtainMessage(BT_CONNECT_FAILED);
                    msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_bind_thread_cannot_get_device_info);
                    handler.sendMessage(msg);
                }
            }


        }

        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            startBleData();
        }
    };

    @SuppressLint("MissingPermission")
    private void enableNotification(BluetoothGatt bluetoothGatt, boolean enable, BluetoothGattCharacteristic characteristic) {
        if (bluetoothGatt == null || characteristic == null) {
            return;
        }
        if (!bluetoothGatt.setCharacteristicNotification(characteristic, enable)) {
            return;
        }
        //获取到Notify当中的Descriptor通道  然后再进行注册
        BluetoothGattDescriptor clientConfig = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
        if (clientConfig == null) {
            return;
        }
        if (enable) {
            clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        } else {
            clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        }
        bluetoothGatt.writeDescriptor(clientConfig);
    }

    @SuppressLint("MissingPermission")
    private void startBleData() {
        if (bleWriteCharacteristic != null) {
            //手机向设备发送消息，通知设备给手机发送相关的设备信息
            bleWriteCharacteristic.setValue(ParseOriginEcgData.packEcgDeviceInfoCmd());
        }
        Log.e("TAG", "startBleData  setValue(start) 特征值设置开始命令");
        try {
            if (mBleGatt != null && mBleGatt.connect()) {
                //通过ble发送数据消息
                boolean result = mBleGatt.writeCharacteristic(bleWriteCharacteristic);
                Log.e("TAG", "startBleData 0 write(start): " + result + "  往蓝牙连接写入开始命令 第一次");
            }
        } catch (Exception e) {
            e.printStackTrace();
            Message msg = handler.obtainMessage(BT_CONNECT_FAILED);
            msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_bt_broken);
            handler.sendMessage(msg);
        }
    }

    @SuppressLint("MissingPermission")
    public void scanBleDevice() {
        scanSwitch = true;
        ScanSettings scanSettings = new ScanSettings.Builder()
                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                .build();
        bleScanner.startScan(null, scanSettings, scanCallback);//开启搜索蓝牙
    }

    ScanCallback scanCallback = new ScanCallback() {
        @SuppressLint("MissingPermission")
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            BluetoothDevice device = result.getDevice();
            if (device == null) {
                return;
            }
            if (TextUtils.isEmpty(device.getName())) {//F0:39:BD:27:04:4B
                return;
            }
            Log.e("TAG", "蓝牙设备Name：" + device.getName());
            if (device.getName().contains("WWK")) {
                scanSwitch = false;
                PreferenceUtils.getInstance().setDeviceBluetoothType(false);
                bluetoothDevice = device;
                connectBleDevice();
            }
        }
    };

    @SuppressLint("MissingPermission")
    @Override
    public void run() {
        super.run();
        scanBleDevice();
        int scanCount = 0;
        while (scanSwitch) {
            try {
                scanCount++;
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.e("TAG", "while " + scanCount);
            if (scanCount > 100) {// 搜索2分钟
                scanSwitch = false;
                bleScanner.stopScan(scanCallback);
                if (bluetoothDevice == null) {
                    //搜索2分钟后，仍然没有搜索到，停止搜索
                    PreferenceUtils.getInstance().setDeviceBluetoothType(true);
                    Log.e("TAG", "ble Device is null");
                    Message msg = handler.obtainMessage(BT_CONNECT_DEVICE_ERROR);
                    msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_bind_thread_check_device);
                    handler.sendMessage(msg);
                }
                Log.e("TAG", ((float) (scanCount / 60)) + "分钟扫描结束" + scanCount + "  " + scanSwitch);
            }
        }
    }
}
